#!/bin/bash
# -*- coding: utf-8 -*-
import addUserProfileCF
from start import getAverage, loadMovieLensTrain, getRating


############### 计算预测分数与实际分数得平均绝对误差 ###########

##==================================================================
##	求每个用户的平均绝对误差
##	getMAUE（）
##	predict:预测分；real：真实评分
##	prefer:用户项目预测分与真实评分集合：
##      格式如{'user1':{itemid1:abs(predict-real), itemid2:abs(predict-real),, ,,}, {,,,}}
##==================================================================

def getMAUE(userid, prefer):
    sum1 = 0  # 用户评分与预测分之差的绝对值之和
    count = 0  # 用户评价过的项目之和
    for item in prefer[userid]:
        sum1 = sum1 + prefer[userid][item]  #
        count = count + 1  # 评价项目总数
    return sum1 / count


##==================================================================
##	求系统平均绝对误差
##	getMAE（）
#    	count=0  #用户个数之
#	summae=0 #所有用户的maue之和
##	predict:预测分；real：真实评分
##	prefer:用户项目预测分与真实评分集合：
##       格式如{'user1':{itemid1:abs(predict-real), itemid2:abs(predict-real),, ,,}, {,,,}}
##==================================================================
def getMAE(prefer):
    count = 0
    summae = 0
    for userid in prefer:
        summae = summae + getMAUE(userid, prefer)
        count = count + 1
    return summae / count


## 计算召回率  正确预测为正（推荐给用户的物品个数）占全部正样本(用户所有喜欢的物品包含推荐的和没有推荐的)的比例
## recall = tp/allLove
## 计算精准率
## precision = tp/(tp+fp) 正确预测为正（推荐给用户且用户喜欢的）占全部预测为正（所有推荐的)的比例
def recallAndPrecision(fileTrain, fileTest, fileRecommend):
    preferTrain = loadMovieLensTrain(fileTrain)  # 加载训练集 训练集的偏好矩阵
    preferTest = loadMovieLensTrain(fileTest)  # 加载测试集
    preferRecommend = loadRecommend(fileRecommend)

    tp = 0  # 推荐物品中用户喜欢的
    allLove = 0  # 测试集中用户喜欢的所有物品
    allRecommend = 0 # 所有预测喜欢并且推荐的物品
    for userid in preferTest:  # test集中每个用户
        for item in preferTest[userid]:  # 对于test集合中每一个项目用base数据集,CF预测评分
            avg = getAverage(preferTrain, userid)
            if userid in preferRecommend.keys() and item in preferRecommend[userid] and preferRecommend[userid][item] > avg:  # 改成大于用户在训练集中的的平均评分 就推荐给他
                if preferTest[userid][item] > avg:
                    tp += 1
                allRecommend += 1
            if preferTest[userid][item] > avg:
                allLove += 1
    recall = tp/allLove
    precision = tp/allRecommend
    return [recall, precision]


def loadRecommendAbs(fileName):
    fr = open(fileName)
    index = 0
    prefer = {}

    ##   第2步逐行读取:
    delim = '\t'
    line0 = fr.readlines()

    ##   接着进行使用strip和split处理:
    while index < len(line0) - 1:
        index = index + 1
        line2 = line0[index].strip().split(delim)

        ##  第3步将字符串形式转化为float类型的数据形式：
        (userid, itemid, predict, real) = [float(line) for line in line2]
        absitem = itemid
        prefer.setdefault(userid, {})
        if real != 0:  # 用户已评过分
            prefer[userid][absitem] = abs(float(predict) - real)
        else:
            prefer[userid][absitem] = 0
    return prefer

def loadRecommend(fileName):
    fr = open(fileName)
    index = 0
    prefer = {}

    ##   第2步逐行读取:
    delim = '\t'
    line0 = fr.readlines()

    ##   接着进行使用strip和split处理:
    while index < len(line0) - 1:
        index = index + 1
        line2 = line0[index].strip().split(delim)

        ##  第3步将字符串形式转化为float类型的数据形式：
        (userid, itemid, predict, real) = [line for line in line2]
        prefer.setdefault(userid, {})
        prefer[userid][itemid] = float(predict)
    return prefer

############    主程序   ##############
def testEvaluate(fileName, baseName, testName):
    print(u"\n--------------start... -----------\n")
    # MAE = getMAE(loadRecommendAbs(fileName))
    # print("MAE : %f \n" % MAE)
    test = recallAndPrecision(baseName, testName, fileName)
    print("recall : %f \n" % test[0])
    print("precision : %f \n" % test[1])

############    主程序   ##############
def myTestEvaluate(fileName, baseName, testName):
    print(u"\n--------------start... -----------\n")
    MAE = getMAE(loadRecommendAbs(fileName))
    print("MAE : %f \n" % MAE)
    test = recallAndPrecision(baseName, testName, fileName)
    print("recall : %f \n" % test[0])
    print("precision : %f \n" % test[1])
